using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.Logic;
using NetProtocol.POD;

namespace IQIGame.Onigao.GamePlay
{
    public partial class BattleRenderQueueController : BattleRenderBaseController
    {
        private Queue<IBaseBattleCommandView> updateQueue = new Queue<IBaseBattleCommandView>();

#if UNITY_EDITOR
        public Queue<IBaseBattleCommandView> Queue => this.updateQueue;
#endif

        private List<WaitingItem> _waitingCommand = new List<WaitingItem>();

        private Dictionary<int, int> _unitDialog = new Dictionary<int, int>();
        private CancellationTokenSource _cancel = new CancellationTokenSource();

        public override async UniTask Initialize(BattleRenderContrller rRenderCtrl)
        {
            await base.Initialize(rRenderCtrl);
            this.mCurCmd = null;
            this.Do().Forget();
        }

        public void Clear()
        {
            this.updateQueue.Clear();
        }

        private IBaseBattleCommandView mCurCmd;
        public IBaseBattleCommandView curCmd => this.mCurCmd;

        private bool pause;
        private bool end;

        private async UniTaskVoid Do()
        {
            while (true)
            {
                // 先判断是否需要插入，不需要再取常规队列中获取
                if (!this.pause && this.mCurCmd == null && this.updateQueue.TryDequeue(out this.mCurCmd))
                {
                    // 常规处理
                    var rView = this.mCurCmd;
                    // 不一定所有的行为都有Unit
                    if (await rView.PlayUpdate(false))
                    {
                        rView.Free();
                    }
                    this.mCurCmd = null;
                }
                else
                {
                    await UniTask.Yield();
                }
                if (this.end)
                {
                    return;
                }
            }
        }

        public void EnQueue(List<BattleUpdatePOD> rList)
        {
            var rCmdViews = ListPool<IBaseBattleCommandView>.Get();

#region 遍历cmd,按需进行处理,若无特殊处理直接转为cmdview

            for (int i = 0; i < rList.Count; i++)
            {
                var rUpdatePOD = rList[i];
                // 如果有对数据打包进行处理的情况，在这里处理

                // 常规小数据块处理
                if (this.TryParseUpdate(rUpdatePOD, out var rCommandView))
                {
#region 将靠后的startPart 中的aimoveType 设置进castSkill 用来做特殊移动模式的表现

                    // 当前情况下，castskill若存在一定在传入list的首位
                    if (rCmdViews.Count > 0 &&
                        rUpdatePOD.type == (int)EBattleUpdateType.StartPart &&
                        rUpdatePOD.data is BattleCommand_StartPart rStartPart &&
                        rCmdViews[0] is BattleCommandView_CastSkill rCastSkillCmd &&
                        rStartPart.skillID == rCastSkillCmd.skillID &&
                        rStartPart.aiMoveType != 0)
                    {
                        rCastSkillCmd.aiMoveType = rStartPart.aiMoveType;
                    }

#endregion

                    rCmdViews.Add(rCommandView);
                }
                else
                {
                    LogGame.LogError("解析失败");
                }
            }

#endregion

            for (int i = 0; i < rCmdViews.Count; i++)
            {
                var rView = rCmdViews[i];
                this.EnQueue(rView);
            }
            ListPool<IBaseBattleCommandView>.Put(rCmdViews);
        }

        public void EnQueue(IBaseBattleCommandView rCommand)
        {
            this.updateQueue.Enqueue(rCommand);
        }

        public bool TryPeek(out IBaseBattleCommandView rCmd)
        {
            return this.updateQueue.TryPeek(out rCmd);
        }

        public bool InWaitCastSkill(out BattleCommandView_PermitCast rPermit, UnitView rUnit = null)
        {
            rPermit = this.mCurCmd as BattleCommandView_PermitCast;
            return rPermit != null && (rUnit == null || rUnit.GUID == rPermit.executerID);
        }

#region 命中等待

        public bool InWaitingBulletHit()
        {
            return this._waitingCommand.Count > 0;
        }

        public void AddWaitingAction(IBaseBattleCommandView rCommand)
        {
            if (rCommand == null)
            {
                return;
            }
            for (int i = 0; i < this._waitingCommand.Count; i++)
            {
                var rItem = this._waitingCommand[this._waitingCommand.Count - 1 - i];
                if (!rItem.addComplete)
                {
                    rItem.cmds.Add(rCommand);
                    if (rCommand is BattleCommandView_SkillEffectiveEnd rResponse && rResponse.command.responseGUID == rItem.guid)
                    {
                        rItem.addComplete = true;
                    }
                    return;
                }
            }
            rCommand.PlayUpdate(true).Forget();
        }

        public void AddWaitingQueue(int responseGUID)
        {
            var rWaiting = ClassPool.Get<WaitingItem>();
            rWaiting.guid = responseGUID;
            this._waitingCommand.Add(rWaiting);
        }

        public async UniTaskVoid OnWaitComplete(int responseGUID)
        {
            var rItemIndex = -1;
            var nLen = this._waitingCommand.Count;
            for (int i = 0; i < nLen; i++)
            {
                var nIndex = nLen - 1 - i;
                if (this._waitingCommand[nIndex].guid == responseGUID)
                {
                    rItemIndex = nIndex;
                    break;
                }
            }
            if (rItemIndex != -1)
            {
                var rItem = this._waitingCommand[rItemIndex];
                this._waitingCommand.RemoveAt(rItemIndex);
                var rCmds = rItem.cmds;
                for (int i = 0; i < rCmds.Count; i++)
                {
                    var rCmd = rCmds[i];
                    await rCmd.PlayUpdate(true);
                    rCmd.Free();
                }
                rCmds.Clear();
                ListPool<IBaseBattleCommandView>.Put(rCmds);
            }
        }

        private class WaitingItem : IReusableClassWithFree
        {
            public int guid;
            public List<IBaseBattleCommandView> cmds = new List<IBaseBattleCommandView>();
            public bool addComplete;

            public uint MaxStore => 10;

            public void OnReset()
            {
                this.guid = default;
                this.cmds.Clear();
                this.addComplete = false;
            }

            public void Free()
            {
                ClassPool.Put(this);
            }
        }

#endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="unitGUID"></param>
        /// <param name="dialogType">1 回合开始判断血量</param>
        public void AddDialog(int unitGUID, int dialogType)
        {
            this._unitDialog.TryAdd(unitGUID, dialogType);
        }

        public bool TryGetDialog(int unitGUID, int dialogType)
        {
            if (this._unitDialog.TryGetValue(unitGUID, out var nDialogType) && nDialogType == dialogType)
            {
                this._unitDialog.Remove(unitGUID);
                return true;
            }
            return false;
        }

        protected override void OnDispose()
        {
            if (this._cancel != null)
            {
                this._cancel.Cancel();
                this._cancel.Dispose();
                this._cancel = null;
            }
            this.end = true;
        }
        
        public BattleCommandView_End CreateEndCommandView(BattleEndPOD rEndPOD)
        {
            var rView = ClassPool.Get<BattleCommandView_End>();
            rView.Initialize(null, 0, this._cancel);
            rView.battleEndPod = rEndPOD;
            return rView;
        }
    }
}